package com.eastedu.superise.handler;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.eastedu.client.file.model.FileSignatureRequest;
import com.eastedu.client.file.model.FileSignatureResponse;
import com.eastedu.client.file.model.FileUpdateRequest;
import com.eastedu.manager.FileManager;
import com.eastedu.repository.file.FileOriginalPO;
import com.eastedu.superise.CustomDataClassRowMapper;
import com.eastedu.util.CosUtils;
import com.eastedu.util.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

import java.nio.file.Path;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 【回滚】文件归档
 *
 * @author zhangzhishuai
 */
@Slf4j
public abstract class AbstractFileArchiveRollbackTemplate<M> extends AbstractHistoricalDataHandler<M> {

    private final FileManager fileManager;
    private final JdbcTemplate jdbcTemplate;

    public AbstractFileArchiveRollbackTemplate(FileManager fileManager, JdbcTemplate jdbcTemplate) {
        this.fileManager = fileManager;
        this.jdbcTemplate = jdbcTemplate;
    }

    public void start() {
        log.info("文件回滚归档定时任务持续运行中......");
        List<M> resources = jdbcTemplate.query(getSql(), new CustomDataClassRowMapper<>(super.getClazz()));
        if (CollectionUtils.isEmpty(resources)) {
            log.info("任务同步完成！");
            return;
        }
        AtomicInteger total = new AtomicInteger(resources.size());
        resources.forEach(resource -> {
            try {
                this.callback(resource);
            } catch (SQLException e) {
                log.error("执行出错：", e);
            } finally {
                log.info("剩余数据量： {}", total.decrementAndGet());
            }
        });
        log.info("任务同步完成！");
    }

    protected void upload(FileOriginalPO fileInfo, Path originalFilePath) {
        String newFileName = fileInfo.getFileName();
        FileSignatureResponse fileSignature = this.getUploadFileSignature(newFileName, fileInfo.getExtension(), originalFilePath);
        CosUtils.uploadFile(fileSignature, fileSignature.getFile().getPath(), originalFilePath);
        fileManager.putFile(fileSignature.getFile().getId(), new FileUpdateRequest());
        log.info("{}:上传文件成功：文件Id：{}，本地文件路径：{}，云端路径：{}",
                fileInfo.getId(), fileSignature.getFile().getId(), originalFilePath, fileSignature.getFile().getPath());
    }

    protected Path download(String fileId, FileOriginalPO fileInfo) {
        String downloadUrl = StrUtil.concat(false, fileInfo.getServer(), fileInfo.getPath());
        Path workdir = FileUtils.buildWorkdir(fileId);
        log.info("{}:创建临时工作目录成功：{}", fileId, workdir);
        log.info("{}:下载原始文件开始：文件下载地址：{}", fileId, downloadUrl);
        long startTime = System.currentTimeMillis();
        Path originalFilePath = FileUtils.downloadFile(downloadUrl, fileInfo.getMd5(), fileInfo.getExtension(), workdir);
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        log.info("{}:下载原始文件成功：文件下载地址：{}，临时文件路径：{}，耗时：{}ms",
                fileId, downloadUrl, originalFilePath, duration);
        return originalFilePath;
    }

    private FileSignatureResponse getUploadFileSignature(String fileName, String fileExtension, Path path) {
        FileSignatureRequest fileSignatureRequest = this.createFileSignatureRequest(fileName, fileExtension, path);
        try {
            return fileManager.postFileSignature(fileSignatureRequest);
        } catch (Exception e) {
            log.error("调用文件服务获取文件上传签名失败", e);
            throw e;
        }
    }

    public FileSignatureRequest createFileSignatureRequest(String fileName, String fileExtension, Path path) {
        String md5 = FileUtils.calcMd5(path);
        Long size = FileUtils.calcSize(path);
        FileSignatureRequest fileSignatureRequest = new FileSignatureRequest();
        fileSignatureRequest.setSize(size);
        fileSignatureRequest.setMd5(md5);
        fileSignatureRequest.setExtension(fileExtension);
        fileSignatureRequest.setFileName(fileName);
        fileSignatureRequest.setClient("resource-date-sync");
        fileSignatureRequest.setProvider("tencent");
        fileSignatureRequest.setMethod("sts");
        fileSignatureRequest.setGenre(1);
        return fileSignatureRequest;
    }
}
